package com.ford.microservices.accounts;

import org.apache.commons.math3.random.RandomDataGenerator;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Logger;

@Configuration
@ComponentScan
@EntityScan("com.ford.microservices.accounts")
@EnableJpaRepositories("com.ford.microservices.accounts")
@PropertySource("classpath:db-config.properties")
public class AccountsConfiguration {

    protected Logger logger;

    public AccountsConfiguration() {
        logger = Logger.getLogger(getClass().getName());
    }

    /**
     * Creates an in-memory "checkIn and rewards" database populated with test data for fast
     * testing
     */
    @Bean
    public DataSource dataSource() {
        logger.info("dataSource() invoked");

        // Create an in-memory H2 relational database containing some demo
        // accounts.
        DataSource dataSource = (new EmbeddedDatabaseBuilder()).addScript("classpath:testdb/schema.sql")
                .addScript("classpath:testdb/data.sql").build();

        logger.info("dataSource = " + dataSource);

        // Sanity check
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        List<Map<String, Object>> accounts = jdbcTemplate.queryForList("SELECT id FROM FORD_ACCOUNT WHERE id > 0");
        logger.info("System has " + accounts.size() + " accounts");

        // Populate with random balances
        Random rand = new Random();
        for (Map<String, Object> item : accounts) {
            Long id = (Long) item.get("id");
            Long balance = new RandomDataGenerator().nextLong(1000, 10000) * 10;
            String userName = "ford_" + id;
            String password = passwordEncoder().encode("password");
            jdbcTemplate.update("UPDATE FORD_ACCOUNT SET balance = ?, USERNAME = ?, PASSWORD = ?, ROLE = ? WHERE id = ?",
                    balance, userName, password, "SALES",id);
        }

        return dataSource;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
